package com.minimalist.common.config.easyexcel;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson2.JSON;
import com.minimalist.common.config.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Excel数据读取监听器
 *
 * @author 11987
 */
public class ExcelDataListener<T> extends AnalysisEventListener<T>{
    private static final Logger log = LoggerFactory.getLogger(ExcelDataListener.class);

    /**
     * 数据列表
     */
    private final List<T> list = new ArrayList<>();

    /**
     * 批量处理阈值，达到这个数量后进行批量插入
     */
    private final int batchSize;

    /**
     * 数据处理器，用于将数据插入数据库
     */
    private final Consumer<List<T>> dataHandler;

    /**
     * 总处理数量
     */
    private int totalCount = 0;

    /**
     * 获取处理的数据总数
     *
     * @return 数据总数
     */
    public int getTotalCount() {
        return totalCount;
    }

    /**
     * 构造函数
     *
     * @param dataHandler 数据处理器
     */
    public ExcelDataListener(Consumer<List<T>> dataHandler){
        this(1000, dataHandler);
    }

    /**
     * 构造函数
     *
     * @param batchSize   批量处理阈值
     * @param dataHandler 数据处理器
     */
    public ExcelDataListener(int batchSize, Consumer<List<T>> dataHandler){
        this.batchSize = batchSize;
        this.dataHandler = dataHandler;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void invoke(Object data, AnalysisContext context){
        if (ObjectUtil.isNull(data)){
            return;
        }
        // 添加到数据列表
        list.add((T) data);
        totalCount++;
        log.info("Excel数据读取成功，当前处理第{}条数据，数据为：{}", totalCount
                , JSON.toJSONString(data));
        // 达到批量处理阈值，进行数据处理
        if (list.size() >= batchSize){
            doProcess();
            // 清空列表
            list.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context){
        // 处理剩余数据
        if (CollectionUtil.isNotEmpty(list)){
            doProcess();
        }
        log.info("Excel数据读取完成，共处理{}条数据", totalCount);
    }

    /**
     * 处理数据
     */
    @Transactional(rollbackFor = Exception.class)
    private void doProcess(){
        log.info("开始处理Excel数据，共{}条数据", list.size());
        try{
            if (dataHandler != null){
                dataHandler.accept(list);
                log.info("Excel数据处理成功，共处理{}条数据", list.size());
            }
        } catch (Exception e){
            log.error("Excel数据处理异常", e);
            throw new BusinessException("Excel数据处理失败：" + e.getMessage());
        }
    }

    /**
     * 获取当前缓存的数据列表
     *
     * @return 数据列表
     */
    public List<T> getDataList(){
        return list;
    }
}

